import { useState, useLayoutEffect, useDebugValue } from 'react';

type cb = React.Dispatch<any>;

function createShare<T>(defaultValue: T, label = 'createShare') {
  const listeners: cb[] = [];
  let store: T = defaultValue; // 共享这个状态
  /**
 * 提供共享数据源及其变更通知
 * @param initState
 */
  function useProvide(state: T) {
    useDebugValue(label);
    // 需要马上注册，因后面 useInject 可能马上用到
    useLayoutEffect(() => {
      store = state;
      listeners.forEach(setState => setState(state));
    }, [state]);
  }

  /**
   * 根据 path 返回共享数据源，变化后将返回更新的共享状态
   * @param path 共享数据源的访问路径或命名空间
   */
  function useInject(): [T] {
    useDebugValue(label);
    const [state, setState] = useState(store);
    // 组件退出，取消订阅
    useLayoutEffect(() => {
      setState(store);
      listeners.push(setState); // 上来就订阅，不等
      return () => {
        const index = listeners.findIndex(cb => cb === setState);
        listeners.splice(index, 1);
      };
    }, []);
    return [state];
  }

  return {
    useProvide,
    useInject,
  }
}

export default createShare;
export { createShare };
